package jp.aist.gtrc.plus.scheduler.job;

import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collection;

import jp.aist.gtrc.plus.scheduler.SchedulerOptions;
import jp.aist.gtrc.plus.scheduler.specific.pbs.status.PBSJobStatus;
import jp.aist.gtrc.plus.scheduler.status.JobStatus;
import jp.aist.gtrc.plus.scheduler.job.SortScheduler;
import jp.aist.gtrc.plus.scheduler.sys.SchedulerException;
import jp.aist.gtrc.plus.scheduler.util.CollectionUtil;
import jp.aist.gtrc.plus.scheduler.util.Sorter;
import jp.aist.gtrc.plus.scheduler.util.SortKey;


public class TwoLevelScheduler  extends Scheduler {

        protected static final Logger logger = Logger.getLogger(TwoLevelScheduler.class);

        private EdfScheduler firstScheduler;
        private FairshareScheduler secondScheduler;

	public void init(SchedulerOptions options) throws SchedulerException {
                firstScheduler = new EdfScheduler();
                firstScheduler.init(options);
                secondScheduler = new FairshareScheduler();
                secondScheduler.init(options);
	}

	public JobStatus selectJob(Collection<JobStatus> jobs) {

		if (CollectionUtil.isEmpty(jobs))
			return null;

                Collection<JobStatus> qosJobs = getQoSJobs(jobs);

                if (!CollectionUtil.isEmpty(qosJobs)) { // first level
                   JobStatus selectedJob = firstScheduler.selectJob(qosJobs);
//System.out.println("Job " + selectedJob.getJobID() + " selected by deadline");                   
logger.debug("Job " + selectedJob.getJobID() + " selected by deadline");                   
                   return selectedJob;
                } else { // second level
                   Collection<JobStatus> freeJobs = new ArrayList<JobStatus>(jobs);
                   freeJobs.removeAll(qosJobs);
                   JobStatus selectedJob = secondScheduler.selectJob(freeJobs);
//System.out.println("Job " + selectedJob.getJobID() + " selected by fairshare");                   
logger.debug("Job " + selectedJob.getJobID() + " selected by fairshare");                   
                   return selectedJob;
                }

	}

        private Collection<JobStatus> getQoSJobs(Collection<JobStatus> jobs) {
                Collection<JobStatus> qosJobs = new ArrayList<JobStatus>();
                for (JobStatus jobStatus : jobs) {
                   if ( ((PBSJobStatus) jobStatus).isQoSJob()) {
                      qosJobs.add(jobStatus);
                   }
                }
                return qosJobs;
        }

        /*
         * Update status only for not QoS jobs
         */
        public void updateStatus(Collection<JobStatus> allJobs) {
           Collection<JobStatus> freeJobs = new ArrayList<JobStatus>();
           for (JobStatus jobStatus : allJobs) {
              if (!((PBSJobStatus) jobStatus).isQoSJob())
                 freeJobs.add(jobStatus);
           }

           secondScheduler.updateStatus(freeJobs);

        }

}
